<?php


namespace fize\think\model;

use Closure;
use think\Collection;
use think\db\Query;
use think\Model;

/**
 * 模型基类
 */
abstract class Common extends Model
{
    /**
     * 查找单条记录
     * @param mixed        $data  主键值或者查询条件（闭包）
     * @param array|string $with  关联预查询
     * @param bool         $cache 是否缓存
     * @return null|static
     */
    public static function get($data, $with = [], bool $cache = false): ?\fize\think\model\Model
    {
        if (is_null($data)) {
            return null;
        }

        if (true === $with || is_int($with)) {
            $cache = $with;
            $with = [];
        }
        $query = static::parseQuery($data, $with, $cache);

        return $query->find($data);
    }

    /**
     * 查找所有记录
     * @param mixed        $data  主键列表或者查询条件（闭包）
     * @param array|string $with  关联预查询
     * @param bool         $cache 是否缓存
     * @return Collection
     */
    public static function all($data = null, $with = [], bool $cache = false): Collection
    {
        if (true === $with || is_int($with)) {
            $cache = $with;
            $with = [];
        }
        $query = static::parseQuery($data, $with, $cache);

        return $query->select($data);
    }

    /**
     * 分析查询表达式
     * @param mixed        $data  主键列表或者查询条件（闭包）
     * @param array|string $with  关联预查询
     * @param bool         $cache 是否缓存
     * @return Query
     */
    protected static function parseQuery(&$data, $with, bool $cache): Query
    {
        $result = self::withJoin($with)->cache($cache);
        if (is_array($data) && key($data) !== 0) {
            $result = $result->where($data);
            $data = null;
        } elseif ($data instanceof Closure) {
            call_user_func_array($data, [&$result]);
            $data = null;
        } elseif ($data instanceof Query) {
            $result = $data->withJoin($with)->cache($cache);
            $data = null;
        }

        return $result;
    }

    /**
     * @param array  $data
     * @param array  $where
     * @param array  $allowField
     * @param string $suffix
     */
    public static function update(array $data, $where = [], array $allowField = [], string $suffix = '')
    {
        if (!isset($data['id']) && isset($where['id'])) {
            $data['id'] = $where['id'];
        }
        parent::update($data, $where, $allowField, $suffix);
    }
}